#include <iostream>
#include <stack>

using namespace std;

int m, n, roomNum = 0, curRoomAera;
int map[50][50], color[50][50] = {0};

struct Room
{
    int x, y;
    Room(int x, int y) : x(x), y(y) {}
};
//用栈解决：
void dfs(int X, int Y)
{
    stack<Room> stk;
    stk.push(Room(X, Y));
    int x, y;
    while (!stk.empty())
    {
        Room topRoom = stk.top();
        x = topRoom.x;
        y = topRoom.y;
        if (color[x][y])
            stk.pop();
        else
        {
            curRoomAera++;
            color[x][y] = roomNum;                                     //标记栈顶元素
                                                                       //坑爹啊......&（按位与）运算符的优先级小于 == ，所以必须加括号
            if (((map[x][y] & 1) == 0) && (y > 0) && !color[x][y - 1]) //千万注意！&1==0时对应的一定是y-1，即必须向左走
                stk.push(Room(x, y - 1));
            if (((map[x][y] & 2) == 0) && (x > 0) && !color[x - 1][y]) //千万注意！&2==0时对应的一定是x-1，即必须向上走
                stk.push(Room(x - 1, y));
            if (((map[x][y] & 4) == 0) && (y + 1 < n) && !color[x][y + 1]) //千万注意！&4==0时对应的一定是y+1，即必须向右走
                stk.push(Room(x, y + 1));
            if (((map[x][y] & 8) == 0) && (x + 1 < m) && !color[x + 1][y]) //千万注意！&8==0时对应的一定是x+1，即必须向下走
                stk.push(Room(x + 1, y));
        }
    }
}

int main()
{
    int maxRoomAero = 0;
    cin >> m >> n;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            cin >> map[i][j];
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            if (!color[i][j])
            {
                roomNum++;
                curRoomAera = 0;
                dfs(i, j);
                if (curRoomAera > maxRoomAero)
                    maxRoomAero = curRoomAera;
            }
    cout << roomNum << endl
         << maxRoomAero << endl;
}